<?php
// +----------------------------------------------------------------------
// | najing [ 通用后台管理系统 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2020 http://www.najingquan.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: 救火队队长
// +----------------------------------------------------------------------

namespace app\cardeadmin\controller;

use app\common\controller\AdminController;
use app\common\model\AlipayError;
use app\common\model\ApiEmail;
use app\common\model\ApiOther;
use app\common\model\ApiTranRefund;
use app\common\model\ApiTranReversal;
use app\common\model\CdApiAccept;
use app\common\model\CdApiLog;
use app\common\model\IndexError;
use app\common\model\KeyLog;
use app\common\model\LssApiError;
use app\common\model\LssApiLog;
use app\common\model\ManageLog;
use app\common\model\UserFace;
use app\common\model\UserIceLog;
use app\common\model\UserLog;
use app\common\model\ApiLog;
use app\common\model\ApiError;
use think\facade\Db;
use think\facade\View;
use app\api\controller\Index;

/**
 * Class Operation
 * @package app\admin\controller
 */
class Log extends AdminController
{
    /**
     * 用户日志列表
     */
    public function index()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new UserLog();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    /**
     * 用户增加，减少，注销卡错误记录
     */
    public function userAction()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new IndexError();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function tranIceUser()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new UserIceLog();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function emailLog()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new ApiOther();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function decLog()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new ApiEmail();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function tranFirstLog()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            return CdApiAccept::tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function manageLog()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new ManageLog();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function tranRefund()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new ApiTranRefund();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function tranReversal()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new ApiTranReversal();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function apiLog()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new CdApiLog();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function apiLogLss()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new LssApiLog();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function apiError()
    {

        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new ApiError();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function changeType()
    {
        $param_id   = input('post.id');
        $re         = Db::name('api_error')->where(['id' => $param_id])->update(['is_rep' => 1]);
        if($re){
            return $this->scs('Change Rep successful.');
        }else{
            return $this->scs('Change Rep failed.');
        }
    }

    /**
     * 修复数据
     */
    public function dataRepair()
    {
        $param_id   = input('post.id');
        $list       = Db::name('api_error')->find($param_id);
        $data_param = $list['data_param'];
        $type       = $list['type'];
        $is_rep     = $list['is_rep'];
        $blog       = true;
        if($is_rep != 1){
            switch ($type){
                //clear时 实际消费 比记录消费 多或少
                case 'card_tran_exception':
                    $data_param = json_decode($data_param , true);
                    $tran_token = $data_param['tran_token'];
                    $result = Index::searchOtherAdmin([
                        'add_url'   => '/transactions/' . $tran_token,
                        'method'    => 'GET',
                        'request_data' => ''
                    ]);
                    $response_state = '';
                    if(isset($result['blog']) && $result['blog']){
                        $response = $result['response'];
                        $response_json = json_decode($response , true);
                        $response_state= $response_json['state'] ?? '';
                    }
                    if($response_state == 'CLEARED'){
                        $tran_amount= $data_param['tran_amount'];
                        $real_tran_amount= $data_param['real_tran_amount'];
                        //查出对应的user_id
                        $tran_list  = Db::name('cards_transactions')->alias('ct')
                            ->join('cards c' ,'c.card_token=ct.card_token')
                            ->field('c.user_id,c.card_num,ct.ctime')
                            ->where(['tran_token' => $tran_token])->find();
                        $user_id    = $tran_list['user_id'];
                        $card_num   = substr($tran_list['card_num'] , -4);
                        $tran_time  = $tran_list['ctime'];
                        //获取用户信息
                        $user_list      = Db::name('user')->find($user_id);
                        $user_name      = $user_list['username'];
                        $current_balance= $user_list['balance'];
                        $change_amount  = $real_tran_amount - $tran_amount;
                        $end_balance= $current_balance - $change_amount;
                        if($end_balance >0){
                            Db::startTrans();
                            try {
                                Db::name('user')->where(['id'=>$user_id])->update(['balance'=>$end_balance]);
                                Db::name('user_cash_log')->save([
                                    'user_id'       => $user_id,
                                    'type'          => $change_amount >0 ? 1 : 0, //这里如果大于0 就往余额中加，反之则减
                                    'action_type'   => 5, //其他
                                    'amount'        => abs($change_amount),
                                    'balance'       => $end_balance,
                                    'desc'          => "Posted from $ {$tran_amount} to $ {$real_tran_amount} Card(**** {$card_num})",
                                    'ctime'         => getUtcTime()
                                ]);
                                //更新错误的状态
                                Db::name('api_error')
                                    ->where(['id'=>$param_id])
                                    ->update(['is_rep'=>1,'desc'=> "Current State is {$response_state}"]);
                                //记录修正值
                                Db::name('cards_tran_repair')->save([
                                    'user_id'       => $user_id,
                                    'tran_token'    => $tran_token,
                                    'state'         => $response_state,
                                    'type'          => ($real_tran_amount - $tran_amount) > 0 ? 0 : 1, //0正1负
                                    'tran_amount'   => $tran_amount,
                                    'real_amount'   => $real_tran_amount,
                                    'amount'        => abs($change_amount),
                                    'ctime'         => getUtcTime(),
                                    'tran_time'     => $tran_time
                                ]);
                                ManageLog::saveManageLog([
                                    'manage_id' => $this->manage_id,
                                    'desc'      => 'Repair Tran Exception',
                                    'content'   => ['username' => $user_name , 'Card' => $card_num , 'tran_token' => $tran_token]
                                ]);
                                Db::name('api_tran_reversal_expire')->where(['tran_token_source'=>$tran_token])->update(['state'=>2]);
                                Db::name('api_tran_reversal')->where(['tran_token_source'=>$tran_token])->update(['state'=>1]);
                                Db::name('api_error')->where(['type'=>'tran_review_reversal_state',
                                    'data_param' => "tran_token:{$tran_token};state:PENDING"])->update(['is_rep'=>1]);
                                Db::commit();
                            } catch (\Exception $e) {
                                $blog = false;
                                var_dump($e->getMessage());
                                Db::rollback();
                            }
                        }else{
                            Db::name('api_error')
                                ->where(['id'=>$param_id])
                                ->update(['desc'=>'Repair failed: Insufficient user balance']);
                            $blog = false;
                        }
                    }else{
                        Db::name('api_error')
                            ->where(['id'=>$param_id])
                            ->update(['desc'=> "Current State is {$response_state}"]);
                        $blog = false;
                    }
                    break;
                case 'tran_review_pending':
                    $list = json_decode($data_param , true);
                    foreach($list as $k=>$v) {
                        $tran_token     = $v['token'];
                        $tran_type      = $v['type'];
                        $state          = $v['state'];
                        $card_token     = $v['card_token'] ?? '';
                        $shop_name      = $v['card_acceptor']['name'] ?? '';        //商户名称
                        $currency_code  = $v['gpa']['currency_code'] ?? '';         //货币类型
                        $request_amount = $v['request_amount'] ?? 0;                //消费的金额
                        $response_memo  = $v['response']['memo'] ?? 'error';        //错误响应
                        $jit_token      = $v['gpa_order_unload']['jit_funding']['token'] ?? '';

                        //银行反馈的消费推送时间
                        $created_time  = isset($v['created_time']) ? utcToUnix($v['created_time']) : getUtcTime();
                        //银行反馈的真实消费时间
                        $user_transaction_time = isset($v['user_transaction_time']) ? utcToUnix($v['user_transaction_time']) : getUtcTime();
                        //country
                        $country        = $v['card_acceptor']['country_code'] ?? '';
                        //original_currency
                        $original_currency = $v['currency_conversion']['network']['original_currency_code'] ?? '';
                        //original_amount
                        $original_amount = $v['currency_conversion']['network']['original_amount'] ?? 0.00;

                        //查询卡对应的用户是什么类型(user_type =1共享模式 =0单卡模式)  卡的余额和状态
                        $user_card_list = Db::name('cards')->alias('c')
                            ->join('user u','u.id=c.user_id')
                            ->field('u.id,u.user_type,u.balance u_balance,
                            c.balance,c.account_balance,c.card_num,c.status')
                            ->where(['c.card_token' => $card_token])
                            ->find();
                        //找不到对应的卡只做第9步的记录
                        if($user_card_list) {
                            $user_type = $user_card_list['user_type'] ?? 0;
                            //单卡模式 balance = 卡余额/共享模式下balance = 已用金额
                            $current_card_balance = $user_card_list['balance'];
                            //共享模式用到的账户余额
                            $current_user_balance = $user_card_list['u_balance'];
                            //共享模式用到的卡限额
                            $current_spend_amount = $user_card_list['account_balance'];
                            //共享模式用到的用户id
                            $current_user_id = $user_card_list['id'];
                            //卡号
                            $current_card_num = substr($user_card_list['card_num'], -4);
                            //当前卡的状态
                            $current_cards_status = $user_card_list['status'];

                            $tran_list = Db::name('cards_transactions')
                                ->where(['tran_token' => $tran_token, 'card_token' => $card_token])
                                ->find();
                            if($tran_list) {
                                //获取消费记录中的金额
                                $tran_amount     = $tran_list['amount'];
                                $jit_token       = $tran_list['jit_token'];
                                Db::startTrans();
                                try {
                                    if($user_type == 1){
                                        $end_user_price  = $current_user_balance - $tran_amount;
                                        //记录钱包日志
                                        Db::name('user_cash_log')->save([
                                            'user_id'       => $current_user_id,
                                            'type'          => 1,
                                            'action_type'   => 3, //3=消费
                                            'amount'        => $tran_amount,
                                            'balance'       => $end_user_price,
                                            'desc'          => "card *** {$current_card_num} tran",
                                            'ctime'         => $user_transaction_time
                                        ]);
                                        //更新卡已用金额
                                        $used_amount = $current_card_balance + $tran_amount;
                                        if(strtolower($country) == 'usa' && $original_currency == 840) {
                                        }else{
                                            $server_amount = round($tran_amount * 0.03 , 2);
                                            Db::name('cards_transactions')->save([
                                                'tran_token'    => $tran_token . "__server",
                                                'jit_token'     => $jit_token,
                                                'card_token'    => $card_token,
                                                'type'          => 'foreign transaction fee',
                                                'state'         => 'COMPLETION',
                                                'amount'        => $server_amount,
                                                'reason'        => 'Success',
                                                'ctime'         => $user_transaction_time,
                                                'utime'         => $created_time,
                                                'is_hold'       => 2,    //2=非冻结，默认=1，冻结
                                                'currency_code' => $currency_code,
                                                'desc'          => $shop_name,
                                                'country'       => $country,
                                                'original_currency' => $original_currency,
                                                'original_amount'=> $original_amount
                                            ]);
                                            //剩余账户余额要减去货转费用
                                            $end_user_price -= $server_amount;
                                            //记录钱包日志
                                            Db::name('user_cash_log')->save([
                                                'user_id'       => $current_user_id,
                                                'type'          => 1,
                                                'action_type'   => 3, //3=消费
                                                'amount'        => $server_amount,
                                                'balance'       => $end_user_price,
                                                'desc'          => "card *** {$current_card_num} tran foreign transaction fee",
                                                'ctime'         => $user_transaction_time + 1
                                            ]);
                                            //有货转时要加上货转费用
                                            $used_amount += $server_amount;
                                        }
                                        //更新账户余额
                                        Db::name('user')->where(['id'=>$current_user_id])
                                            ->update(["balance" => $end_user_price]);
                                        //更新卡已用金额
                                        Db::name('cards')->where(['card_token'=>$card_token])
                                            ->update(["balance" => $used_amount]);
                                    }else{
                                        //计算看最终的卡余额
                                        $end_card_price  = $current_card_balance - $tran_amount;
                                        //记录卡交易记录
                                        Db::name('cards_log')->save([
                                            'card_token'    => $card_token,
                                            'tran_token'    => $tran_token,
                                            'amount'        => $tran_amount,
                                            'balance'       => $end_card_price,
                                            'type'          => $tran_type, //消费授权
                                            'status'        => "PENDING" ,
                                            'reason'        => $state,
                                            'desc'          => $shop_name,
                                            'ctime'         => $user_transaction_time
                                        ]);
                                        if(strtolower($country) == 'usa' && $original_currency == 840) {
                                            //更新卡余额
                                        }else{
                                            $server_amount = round($tran_amount * 0.03 , 2);
                                            Db::name('cards_transactions')->save([
                                                'tran_token'    => $tran_token . "__server",
                                                'jit_token'     => $jit_token,
                                                'card_token'    => $card_token,
                                                'type'          => 'foreign transaction fee',
                                                'state'         => 'COMPLETION',
                                                'amount'        => $server_amount,
                                                'reason'        => 'Success',
                                                'ctime'         => $user_transaction_time,
                                                'utime'         => $created_time,
                                                'is_hold'       => 2,    //2=非冻结，默认=1，冻结
                                                'currency_code' => $currency_code,
                                                'desc'          => $shop_name,
                                                'country'       => $country,
                                                'original_currency' => $original_currency,
                                                'original_amount'=> $original_amount
                                            ]);
                                            //卡余额要减去货转费用
                                            $end_card_price -= $server_amount;
                                            //记录货转卡交易
                                            Db::name('cards_log')->save([
                                                'card_token'    => $card_token,
                                                'tran_token'    => $tran_token . "__server",
                                                'amount'        => $server_amount,
                                                'balance'       => $end_card_price,
                                                'type'          => 'foreign transaction fee',
                                                'status'        => "COMPLETION" ,
                                                'reason'        => "Success",
                                                'desc'          => $shop_name,
                                                'ctime'         => $user_transaction_time + 1,
                                                'utime'         => $created_time
                                            ]);
                                        }
                                        //更新卡余额
                                        Db::name('cards')->where(['card_token'=>$card_token])
                                            ->update(["balance" => $end_card_price]);
                                    }
                                    //更新卡消费记录 资金冻结 2-不冻结
                                    Db::name('cards_transactions')
                                        ->where(['tran_token' => $tran_token])
                                        ->update(["is_hold" => 2,
                                            "utime"   => $created_time]);
                                    //更新错误的状态
                                    Db::name('api_error')
                                        ->where(['id'=>$param_id])
                                        ->update(['is_rep'=>1,'desc'=> "Error Repair"]);
                                    Db::commit();
                                } catch (\Exception $e) {
                                    $error_msg = $e->getMessage();
                                    $blog = false;
                                    dd($error_msg);
                                    Db::rollback();
                                }
                            }
                        }
                    }
                    break;
                case 'tran_review_clearing_unfind':
                    $data_param = json_decode($data_param , true);
                    $tran_token     = $data_param['tran_token'];
                    $business_token = $data_param['business_token'];
                    $card_token     = $data_param['card_token'];
                    $amount         = $data_param['amount'];
                    $currency_code  = $data_param['currency_code'] ?? '';
                    $country        = $data_param['country'] ?? '';
                    $original_currency = $data_param['original_currency'];
                    $original_amount= $data_param['original_amount'];
                    $desc           = $data_param['desc'];
                    $ctime          = getUtcTime();

                    Db::startTrans();
                    try {
                        Db::name('cards_transactions')->save([
                            'tran_token'    => $tran_token . '_forced',
                            'card_token'    => $card_token,
                            'type'          => 'Forced Post Settlement',
                            'state'         => 'COMPLETION',
                            'amount'        => $amount,
                            'is_hold'       => 2,
                            'reason'        => "Success",
                            'currency_code' => $currency_code,
                            'country'       => $country,
                            'original_currency' => $original_currency,
                            'original_amount'   => $original_amount,
                            'desc'              => $desc,
                            'ctime'             => $ctime
                        ]);
                        $card_list = Db::name('cards')->where(['card_token' => $card_token])->find();
                        $card_num  = substr($card_list['card_num'] , -4);
                        $card_balance   = $card_list['balance'];
                        $cur_user_id    = $card_list['user_id'];
                        $user_list      = Db::name('user')->where(['id' => $cur_user_id])->find();
                        $balance        = $user_list['balance'];
                        $user_type      = $user_list['user_type'];

                        if($user_type == 1){
                            $end_user_balance = $balance - $amount;
                            Db::name('user')
                                ->where(['id' => $cur_user_id])
                                ->update(['balance' =>$end_user_balance ]);
                            Db::name('user_cash_log')->save([
                                'user_id'       => $cur_user_id,
                                'type'          => 1,
                                'action_type'   => 3, //3=消费
                                'amount'        => $amount,
                                'balance'       => $end_user_balance,
                                'desc'          => "Forced Post Settlement , due to bank system error （Card **** {$card_num}）",
                                'ctime'         => $ctime
                            ]);
                            //共享模式下 已用金额增加
                            $card_balance += $amount;
                        }else{
                            //单卡模式下 卡余额减少
                            $card_balance -= $amount;
                            if($card_balance >0){
                                Db::name('cards_log')->save([
                                    'card_token'    => $card_token,
                                    'tran_token'    => $tran_token . '_forced',
                                    'amount'        => $amount,
                                    'balance'       => $card_balance,
                                    'type'          => "Forced Post Settlement , due to bank system error",
                                    'status'        => 'COMPLETION',
                                    'reason'        => 'Success',
                                    'desc'          => $desc,
                                    'ctime'         => $ctime
                                ]);
                                Db::name('cards')->where(['card_token' => $card_token])
                                    ->update(['balance' => $card_balance]);
                            }else{
                                $end_user_balance = $balance - $amount;
                                Db::name('user')
                                    ->where(['id' => $cur_user_id])
                                    ->update(['balance' =>$end_user_balance ]);
                                Db::name('user_cash_log')->save([
                                    'user_id'       => $cur_user_id,
                                    'type'          => 1,
                                    'action_type'   => 3, //3=消费
                                    'amount'        => $amount,
                                    'balance'       => $end_user_balance,
                                    'desc'          => "Forced Post Settlement , due to bank system error （Card **** {$card_num}）",
                                    'ctime'         => $ctime
                                ]);
                            }
                        }
                        Db::name('api_error')->where(['id'=>$param_id])->update(['is_rep' => 1]);
                        Db::commit();
                    } catch (\Exception $e) {
                        $blog = false;
                        Db::rollback();
                        Db::name('api_error')->save([
                            'user_id'   => 0,
                            'type'      => "bank_forced_error",
                            'data_param'=> $tran_token,
                            'desc'      => $e->getMessage(),
                            'ctime'     => $ctime,
                        ]);
                    }
                    break;
                default:
                    $blog = false;
                    break;
            }
        }else{
            $blog = false;
        }
        if($blog){
            return $this->scs('Repair successful.');
        }else{
            return $this->scs('Repair failed.');
        }
    }

    public function showDetail()
    {
        $id     = input('get.id');
        $type   = input('get.type');
        $select_year = input('get.select_year');
        $url    = "";
        $db_name= '';
        switch ($type){
            case "tran_accept":
                $db_name = 'cd_api_accept';
                break;
            case "tran_review":
                $db_name = 'api_transactions_review';
                break;
            case "error_log":
                $db_name = 'cd_api_error';
                break;
            case "cd_log":
                $db_name = 'cd_api_log';
                break;
            case "lss_log":
                $db_name = 'lss_api_log';
                break;

        }
        $list  = Db::name($db_name)->where(['id' => $id])->find();

        if($db_name == 'cd_api_error'){
            $request = $list['tran_token'];
            $response= $list['desc'];
        }else{
            $request = $list['request'];
            $response= $list['response'] ?? '';
        }
        View::assign([
            'url'           => $list['url'] ?? $url,
            'request'       => $request,
            'response'      => $response,
        ]);
        View::layout(false);
        return [
            'status'    => 1,
            'datas'     => View::fetch()
        ];
    }

    public function keyLog()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new KeyLog();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function lssLog()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new LssApiError();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function userCheckLog()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new AlipayError();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }

    public function userFaceLog()
    {
        if ($this->request->isAjax()) {
            $request = input('param.');
            $logModel = new UserFace();
            return $logModel->tableDataAdmin($request);
        }
        return  View::fetch();
    }
}